#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

#include <unistd.h>
#include <fcntl.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <errno.h>
#include <signal.h>
#include <time.h>
#include <libgen.h>
#include <dirent.h>
#include <pthread.h>
#include <semaphore.h>
#include <assert.h>
#include <ctype.h>

#include <arpa/inet.h>

#include <sys/types.h>
#include <sys/syscall.h>
#include <sys/ioctl.h>
#include <sys/prctl.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/uio.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/vfs.h>
#include <sys/mount.h>

#include <linux/unistd.h>
#include <linux/if.h>
#include <linux/wireless.h>

#include <net/route.h>

#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netinet/tcp.h>

#include "bb_api.h"
#include "prj_rpc.h"
#include "getopt.h"

#define MCS_CFG_DEFUALT  -2
#define MCS_CFG_AUTO     -1

#define PWR_CFG_DEFUALT  -2
#define PWR_CFG_AUTO     -1

#define CHAN_CFG_DEFUALT  -2
#define CHAN_CFG_AUTO     -1

#define COMPLIANCE_MODE_DEFUALT  -1

static bb_host_t* phost=NULL;
// 频段模式定义
#define BAND_AUTO "Auto"
#define BAND_1_4G "1.4G"
#define BAND_2G   "2G"
#define BAND_5G   "5G"
static bb_dev_handle_t *bb_handle;
static int slot = 0;//-1;   //default slot 0
static int ioctl_slot = -1;
static bool is_event_reg = false;
static bool reg_event = false;
static int timeout = -1;

// 频段设置相关变量
static char *band = NULL;     // 存储通过命令行传入的频段参数
static int direction = -1;    // 方向标识：-1=未设置，0=RX，1=TX
static bool set_minidb = false; // 是否写入minidb（永久生效）

typedef	void *(*ThreadEntryPtrType)(void *);



int MID_UTIL_CreateDetachThread(ThreadEntryPtrType entry, void *para, pthread_t *pid)
{
    pthread_t ThreadId;
    pthread_attr_t attr;

    pthread_attr_init(&attr);
    pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    if(pthread_create(&ThreadId, &attr, entry, para) == 0) {
        pthread_attr_destroy(&attr);
		if(pid)
			*pid = ThreadId;
		return 0;
    }
    pthread_attr_destroy(&attr);
    return -1;
}

void bb_test_Usage(char * name)
{
    printf("Usage: %s [options]\n", name);
    printf("Options:\n");
    printf("\t-h       Print help info \n");
    printf("\t-d       DEV mode\n");
    printf("\t-a       AP mode\n");
    printf("\t-s       Slot id\n");
    printf("\t-S       ioctl slot id\n");
    printf("\t-b       Bandwidth,refers to bb_bandwidth_e\n");
    printf("\t-m       MCS, refers to bb_phy_mcs_e. -1 means auto.\n");
    printf("\t-P       Set power, -1 means auto\n");
    printf("\t-c       Set chan, -1 means auto\n");
    printf("\t-g       get info\n");
    printf("\t-C       Set compliance_mode\n");
    printf("\t-r       Remote role\n");
    printf("\t-G       get cfg\n");
	printf("\t-R       reset cfg\n");
	printf("\t-H       reboot \n");
	printf("\t-k       close all socket\n");
    printf("\t-t       call ioctl with timeout\n");
    printf("\t-e       enable/disable bb\n");
    printf("\t-p       Plug test\n");
    printf("\t-E       Event register test\n");
    printf("\t-T       test if daemon is able to communicate\n");
    printf("\t-i       ip address of daemon\n");
    printf("\t-o       port of daemon\n");
	printf("\t-v       get version\n");
	printf("\t-B       Set band (Auto, 1.4G, 2G, 5G) - TX Auto mode skips setting\n");
    printf("\t-x       Set direction (0:RX, 1:TX)\n");
    printf("\t-M       Save band setting to minidb (persistent after reboot)\n");
    printf("\t-f       Set frame change mode (0 or 1) \n");

}

int ar8030_ioctl(bb_dev_handle_t* pdev, uint32_t request, const void* in, uint16_t in_len, void* out, uint16_t out_len)
{
    int ret = 0;
    bb_remote_ioctl_in_t remote_in = {0};
    bb_remote_ioctl_out_t remote_out = {0};

    if (ioctl_slot < 0) {
        ret = bb_ioctl_ex(pdev, request, in, out, timeout);
    }
    else {
        memcpy(remote_in.data, in, in_len);
        remote_in.len = in_len;
        remote_in.slot = ioctl_slot;
        remote_in.msg_id = request;

        ret = bb_ioctl_ex(pdev, BB_REMOTE_IOCTL_REQ, &remote_in, &remote_out, timeout);
        if (out) {
            memcpy(out, remote_out.data, out_len);
        }
    }

    return ret;
}

void bb_reboot()
{
     bb_set_reboot_t reboot;
    printf("cfg end, reboot!\n");
    reboot.tim_ms = 0;
    bb_ioctl(bb_handle, BB_SET_SYS_REBOOT, &reboot, NULL);

    printf("test end, exit!\n");

 
      
}
void bb_close_socket()
{
 
    printf("bb_close_socket\n");
    
    bb_ioctl(bb_handle, BB_FORCE_CLS_SOCKET_ALL, NULL, NULL);

      
}
void bb_link_status_print(int slot)
{
    bb_get_status_in_t bb_st_in = {0};
    bb_get_status_out_t bb_st_out;

    bb_st_in.user_bmp = (1<<slot);
    bb_ioctl(bb_handle, BB_GET_STATUS, &bb_st_in, &bb_st_out);
    printf("[%d],role=%d,mode=%d,sync_mode=%d,sync_master=%d,cfg_sbmp=0x%0x,rt_sbmp=0x%0x\n",
        0,bb_st_out.role,bb_st_out.mode,
        bb_st_out.sync_mode,bb_st_out.sync_master,bb_st_out.cfg_sbmp,bb_st_out.rt_sbmp);

    printf("slot%d\n",slot);

    printf("dev_%d",0);
    printf("link_status:state=%d,rx_mcs=%d\n",
        bb_st_out.link_status[slot].state,bb_st_out.link_status[slot].rx_mcs);
    printf("user_status:tx_mcs=%d,tx_rf_mode=%d,tx_tintlv_enable=%d,tx_tintlv_len=%d,"
        "tx_tintlv_num=%d,tx_bw=%d,tx_freq=%lu kHz\n",
        bb_st_out.user_status[slot].tx_status.mcs,bb_st_out.user_status[slot].tx_status.rf_mode,
        bb_st_out.user_status[slot].tx_status.tintlv_enable,bb_st_out.user_status[slot].tx_status.tintlv_len,
        bb_st_out.user_status[slot].tx_status.tintlv_num,bb_st_out.user_status[slot].tx_status.bandwidth,
        bb_st_out.user_status[slot].tx_status.freq_khz);

    printf("user_status:rx_mcs=%d,rx_rf_mode=%d,rx_tintlv_enable=%d,rx_tintlv_len=%d,"
        "rx_tintlv_num=%d,rx_bw=%d,rx_freq=%lu kHz\n",
        bb_st_out.user_status[slot].rx_status.mcs,bb_st_out.user_status[slot].rx_status.rf_mode,
        bb_st_out.user_status[slot].rx_status.tintlv_enable,bb_st_out.user_status[slot].rx_status.tintlv_len,
        bb_st_out.user_status[slot].rx_status.tintlv_num,bb_st_out.user_status[slot].rx_status.bandwidth,
        bb_st_out.user_status[slot].rx_status.freq_khz);
}

void bb_info_dump()
{
    int ret;
    int i;

    //get status
    bb_get_1v1_info_in_t one_by_one_info_in = {0};
    bb_get_1v1_info_out_t one_by_one_info_out = {0};

    bb_get_chan_info_out_t chan_info_out;

    bb_get_mcs_in_t mcs_in = { 0 };
    bb_get_mcs_out_t mcs_out = { 0 };

    printf("bb info dump\n");

    //get 1v1 wireless quality
    ret = ar8030_ioctl(bb_handle, BB_GET_1V1_INFO, &one_by_one_info_in, sizeof(one_by_one_info_in), &one_by_one_info_out, sizeof(one_by_one_info_out));
    if(ret){
        printf("[Ioctl Fail]BB_GET_1V1_INFO ERROR,%d !\n", ret);
    }else{
        printf("self-->snr:%d,ldpc_tlv_err :%d, ldpc_num_err:%d,gain_a:%d, gain_b:%d,tx_mcs:%d,tx_chan:%d,tx_power:%d,lna_inner_bypass %d,lna_fem_bypass %d\n",
                one_by_one_info_out.self.snr,
                one_by_one_info_out.self.ldpc_tlv_err_ratio,
                one_by_one_info_out.self.ldpc_num_err_ratio,
                one_by_one_info_out.self.gain_a,
                one_by_one_info_out.self.gain_b,
                one_by_one_info_out.self.tx_mcs,
                one_by_one_info_out.self.tx_chan,
                one_by_one_info_out.self.tx_power,
                one_by_one_info_out.self.lna_inner_bypass,
                one_by_one_info_out.self.lna_fem_bypass);
        printf("peer-->snr:%d,ldpc_tlv_err :%d, ldpc_num_err:%d,gain_a:%d, gain_b:%d,tx_mcs:%d,tx_chan:%d,tx_power:%d,lna_inner_bypass %d,lna_fem_bypass %d\n",
                one_by_one_info_out.peer.snr,
                one_by_one_info_out.peer.ldpc_tlv_err_ratio,
                one_by_one_info_out.peer.ldpc_num_err_ratio,
                one_by_one_info_out.peer.gain_a,
                one_by_one_info_out.peer.gain_b,
                one_by_one_info_out.peer.tx_mcs,
                one_by_one_info_out.peer.tx_chan,
                one_by_one_info_out.peer.tx_power,
                one_by_one_info_out.peer.lna_inner_bypass,
                one_by_one_info_out.peer.lna_fem_bypass);
    }
    //channel info
    ret = ar8030_ioctl(bb_handle, BB_GET_CHAN_INFO, NULL, 0, &chan_info_out, sizeof(bb_get_chan_info_out_t));
    if (ret) {
        printf("[Ioctl Fail]BB_GET_CHAN_INFO ERR, %d !\n", ret);
    }
    else {
        printf("chan_num %d auto_mode %d acs_chan %d work_chan %d\n",
            chan_info_out.chan_num,
            chan_info_out.auto_mode,
            chan_info_out.acs_chan,
            chan_info_out.work_chan);
        for(i=0; i<chan_info_out.chan_num; i++){
            printf("chan %d freq %d power %d\n", i, chan_info_out.freq[i], chan_info_out.power[i]);
        }
    }

    //Get MCS and cur max throughput
    mcs_in.slot = 0;
    mcs_in.dir = BB_DIR_RX;
    ret = ar8030_ioctl(bb_handle, BB_GET_MCS, &mcs_in, sizeof(mcs_in), &mcs_out, sizeof(mcs_out));
    if (ret)
    {
        printf("[Ioctl Fail]BB_GET_MCS ERR, %d !\n", ret);
    }
    else{
        printf("mcs %d TP %d(kbps)\n", mcs_out.mcs, mcs_out.throughput);
    }

    bb_link_status_print(slot);
}

void rx_data_cb(void* arg, void* user)
{
    printf("receive data\n");
}

static void bb_event_hotplug(void* arg, void* user)
{
    int ret = 0;
    bb_event_hotplug_t* plug = (bb_event_hotplug_t*)arg;

    printf("dev hotplug cb id = %d mac = %s status = %s\n", plug->id, plug->bb_mac.mac, plug->status ? "on" : "off");

    if (!plug->status) {
        bb_handle = NULL;
    }
    else {
        int dev_num;
        bb_dev_t** devs=NULL;
        /* get dev list of the 8030 */
        dev_num = bb_dev_getlist(phost,&devs);
        if (dev_num == 0) {
            printf("Get no device!\n");
            return;
        }

        /* Open the dev 8030 */
        bb_handle = bb_dev_open(devs[0]);
        if (!bb_handle) {
            printf("bb_dev_open error\n");
            return;
        }

        bb_dev_freelist(devs);
    }
    if (is_event_reg && bb_handle) {
        reg_event = true;
    }
}

void * bb_event_process(void * args)
{
    int ret = 0;
    while (1) {
        if (reg_event) {
            if (is_event_reg && bb_handle) {

                printf("dump info!\n");
                bb_info_dump();
                printf("dump info done!\n");

                bb_event_callback pcb = NULL;
                bb_set_event_callback_t cb;
                /* Register the rx data callback */
                pcb = (bb_event_callback)rx_data_cb;
                cb.callback = pcb;
                cb.event    = BB_EVENT_PRJ_DISPATCH2;
                cb.user     = (void*)&slot;
                printf("register rx data cb!\n");
                ret = bb_ioctl(bb_handle, BB_SET_EVENT_SUBSCRIBE, &cb, 0);
                if (ret) {
                    printf("set receive callback err! ret = %d\n",ret );
                }
                printf("register rx data cb done!\n");
            }
            reg_event = false;
        }
        usleep(100*1000);
    }
}
void bb_cfg_reset()
{

       bb_ioctl(bb_handle, BB_RESET_CFG, NULL,NULL );
 
      
}
void bb_get_version()
{

    bb_get_sys_info_out_t bb_get_sys_info_out;
    int s32Ret = bb_ioctl(bb_handle, BB_GET_SYS_INFO, NULL, &bb_get_sys_info_out);
    if (s32Ret) {
    printf("BB_GET_SYS_INFO failed s32Ret = %d\n", s32Ret);
    } 
    printf("firmware_ver : %s\n", bb_get_sys_info_out.firmware_ver); 
}


void bb_cfg_dump()
{
    int ret;
    int i = 0;
    int buffLen = 100*1024;
    uint8_t *getData;

    bb_get_cfg_out_t out = {};
    bb_get_cfg_in_t in = {0, 0, 0, 0, sizeof(out.data)-1};
    in.mode = 0;

    getData = malloc(100*1024);
    memset(getData, 0, 100*1024);

    do
    {
        int ret = ar8030_ioctl(bb_handle, BB_GET_CFG, &in, sizeof (bb_get_cfg_in_t), &out, sizeof (bb_get_cfg_out_t));
        if (ret)
        {
            printf("get cfg err! ret %d i %d\n", ret, i);
            return;
        }
        if (in.offset + out.length > buffLen)
        {
            printf("buf overflow !!!!!!!\n");
            return;
        }
        printf("%d:%s",i,out.data);
        ++i;
        memcpy(getData + in.offset, out.data, out.length);
        in.offset += out.length;
        in.seq = i;
        out.data[out.length] = 0;
        memset(out.data, 0, sizeof(out.data));
    } while (out.length > 0);

    printf("get cfg:\n");
    printf("%s\n", getData);

    free(getData);
}

static int set_rx_band()
{
    bb_set_band_mode_t band_mode;
    int ret;

    // 1. 设置频段模式（自动/手动）
    if (strcmp(band, BAND_AUTO) == 0) {
        band_mode.auto_mode = 1;
    } else {
        band_mode.auto_mode = 0;
    }

    ret = ar8030_ioctl(bb_handle, BB_SET_BAND_MODE, &band_mode, sizeof(band_mode), NULL, 0);
    printf("BB_SET_BAND_MODE --> Auto_Mode:%d, Ret:%d\n", band_mode.auto_mode, ret);
    if (ret != 0) {
        printf("Failed to set RX band mode!\n");
        return ret;
    }
    usleep(200 * 1000);  // 等待200ms

    // 2. 手动模式下，设置具体频段
    if (band_mode.auto_mode == 0) {
        bb_set_band_t set_band;
        memset(&set_band, 0, sizeof(set_band));

        // 频段映射
        if (strcmp(band, BAND_2G) == 0) {
            set_band.target_band = 1;
        } else if (strcmp(band, BAND_5G) == 0) {
            set_band.target_band = 2;
        } else if (strcmp(band, BAND_1_4G) == 0) {
            set_band.target_band = 0;
        } else {
            printf("Invalid RX band: %s (supported: Auto/1.4G/2G/5G)\n", band);
            return -EINVAL;
        }

        ret = ar8030_ioctl(bb_handle, BB_SET_BAND, &set_band, sizeof(set_band), NULL, 0);
        printf("BB_SET_BAND --> Target_Band:%d, Ret:%d\n", set_band.target_band, ret);
        if (ret != 0) {
            printf("Failed to set RX target band!\n");
            return ret;
        }
        usleep(200 * 1000);  // 等待200ms，确保设置生效
    }

    printf("RX band setting completed successfully!\n");
    return 0;
}


static int set_tx_band()
{
    bb_set_remote_t set_remote;
    int ret;

    memset(&set_remote, 0, sizeof(set_remote));
    set_remote.slot = BB_SLOT_0;  

    
    // TX选择"Auto"时直接返回
    if (strcmp(band, BAND_AUTO) == 0) {
        printf("TX band set to 'Auto' --> Skip manual band configuration \n");
        return 0;
    }
    // ------------------------------------------------------------------------

    // 手动模式：映射频段
    if (strcmp(band, BAND_1_4G) == 0) {
        set_remote.setting.target_band = 0;
    } else if (strcmp(band, BAND_2G) == 0) {
        set_remote.setting.target_band = 1;
    } else if (strcmp(band, BAND_5G) == 0) {
        set_remote.setting.target_band = 2;
    } else {
        printf("Invalid TX band: %s (supported: Auto/1.4G/2G/5G)\n", band);
        return -EINVAL;
    }

    // 设置需要更新的参数类型（仅更新目标频段）
    set_remote.type_bmp = (1 << BB_REMOTE_TYPE_TARGET_BAND);
    ret = ar8030_ioctl(bb_handle, BB_SET_REMOTE, &set_remote, sizeof(set_remote), NULL, 0);
    printf("BB_SET_REMOTE --> Target_Band:%d, Ret:%d\n", set_remote.setting.target_band, ret);

    if (ret != 0) {
        printf("Failed to set TX band!\n");
        return ret;
    }

    printf("TX band setting completed successfully!\n");
    return 0;
}

static int set_self_band_to_minidb()
{
    uint8_t band_bmp = 0x07; // 默认Auto模式
    
    // 频段映射
    if (strcmp(band, BAND_2G) == 0) {
        band_bmp = 0x02;
    } else if (strcmp(band, BAND_5G) == 0) {
        band_bmp = 0x04;
    } else if (strcmp(band, BAND_AUTO) == 0) {
        band_bmp = 0x07;
    } else {
        printf("Invalid band for minidb: %s (supported: Auto/2G/5G)\n", band);
        return -1;
    }

    // 构造PRJ_CMD_SET_BAND命令
    bb_set_prj_dispatch_in_t set_prj;
    memset(&set_prj, 0, sizeof(set_prj));
    
    prj_rpc_hdr_t* hdr = (prj_rpc_hdr_t*)set_prj.data;
    hdr->cmdid = PRJ_CMD_SET_BAND;  // 设置频段的RPC命令
    
    prj_cmd_set_band_t *set_band = (prj_cmd_set_band_t *)hdr->data;
    set_band->band_bmp = band_bmp;  // 设置频段位图

    // 发送设置命令到设备
    int ret = ar8030_ioctl(bb_handle, BB_SET_PRJ_DISPATCH, &set_prj, sizeof(set_prj), NULL, 0);
    if (ret != 0) {
        printf("Failed to save band to minidb! ret=%d\n", ret);
        return ret;
    }
    
    printf("self Band setting saved to minidb successfully (band_bmp=0x%02X)\n", band_bmp);
    printf("Note: The setting will take effect permanently after reboot\n");
    return 0;
}

static int set_peer_band_to_minidb()
{
    uint8_t band_bmp = 0x07; // 默认Auto模式
    
    // 频段映射
    if (strcmp(band, BAND_2G) == 0) {
        band_bmp = 0x02;
    } else if (strcmp(band, BAND_5G) == 0) {
        band_bmp = 0x04;
    } else if (strcmp(band, BAND_AUTO) == 0) {
        band_bmp = 0x07;
    } else {
        printf("Invalid band for minidb: %s (supported: Auto/2G/5G)\n", band);
        return -1;
    }
    bb_set_prj_dispatch_in_t set_prj;
    memset(&set_prj, 0, sizeof(set_prj));
    prj_rpc_hdr_t* hdr = (prj_rpc_hdr_t*)set_prj.data;
    hdr->cmdid = PRJ_CMD_SET_BAND;
    prj_cmd_set_band_t *set_band = (prj_cmd_set_band_t *)hdr->data;
   // set_band->band_bmp = band;
    set_band->band_bmp = band_bmp; 
    int ret = 0;
    bb_remote_ioctl_in_t remote_in = {0};
    bb_remote_ioctl_out_t remote_out = {0};

    memcpy(remote_in.data, &set_prj, sizeof(bb_set_prj_dispatch_in_t));
    remote_in.len = sizeof(bb_set_prj_dispatch_in_t);
    remote_in.slot = 0;
    remote_in.msg_id = BB_SET_PRJ_DISPATCH;

    // 4. 调用远端 IOCTL
    ret = bb_ioctl(bb_handle, BB_REMOTE_IOCTL_REQ, &remote_in, &remote_out);
    // 5. 结果处理
    if (ret != 0) {
        printf("Failed to save band to minidb! ret=%d\n", ret);
        return ret;
    }
    printf("peer Band setting saved to minidb successfully (band_bmp=0x%02X)\n", band_bmp);
    printf("Note: The setting will take effect permanently after reboot\n");
    return 0;
}

void set_frame_change_mode(int frame_mode)
{
    printf("Setting frame change mode\n");
    bb_set_frame_change_t frame_change;
    frame_change.mode = frame_mode;
    int ret = ar8030_ioctl(bb_handle, BB_SET_FRAME_CHANGE, &frame_change, sizeof(frame_change), NULL, 0);
    if (ret != 0) {
        printf("Failed to set frame change mode! ret = %d\n", ret);
    } else {
        printf("Frame change mode set successfully.\n");
        }
}

int main(int argc, char ** argv)
{
    int s32Ret;
    int ret;
    bool is_ap = false;
    bool is_frame_change = false;
    bool is_getinfo = false;
    bool is_reboot = false;
    bool is_close_all_socket= false;
    bool is_getcfg = false;
	bool is_resetcfg = false;
    bool is_get_version = false;
    bool is_tx_bandwith = false;
  
    
    bool is_enable_bb_rf = false;
    bool is_plug_test = false;
    bool is_connect_test = false;
    int  value;

    int port = BB_PORT_DEFAULT;
    char ip_str[32] = {0};

    int i;
    int dev_num;

    bb_host_t* phost=NULL;
    bb_dev_t** devs=NULL;

    bb_set_mcs_mode_t bb_set_mcs_mode;
    bb_set_mcs_t bb_set_mcs;
    bb_set_bandwidth_t bb_set_bandwidth;
    bb_set_pwr_auto_in_t bb_set_pwr_auto_in;
    bb_set_pwr_mode_in_t bb_set_pwr_mode_in;
    bb_set_pwr_in_t bb_set_pwr_in;
    bb_set_chan_mode_t chan_mode;
    bb_set_band_mode_t band_mode;
    bb_set_chan_t set_chan;
    bb_set_band_t set_band;
    

    int power = PWR_CFG_DEFUALT;
    int mcs = MCS_CFG_DEFUALT;
    int chan = CHAN_CFG_DEFUALT;
    int compliance_mode = COMPLIANCE_MODE_DEFUALT;
    int role = -1;
    int bandwidth = 0;
    int bb_rf_enable = 1;
    int frame_mode = 0;

     printf("init ...\n");

    if(argc == 1){
        bb_test_Usage(argv[0]);
        return -1;
    }

    strcpy(ip_str, "127.0.0.1");

    while((s32Ret = getopt(argc, argv, "hdas:S:ym:b:P:c:gC:r:Gt:e:px:XvhMRkHETi:o:f:")) != -1)
    {
        switch(s32Ret)
        {
            case 'h':
                bb_test_Usage(argv[0]);
                return 0;
            case 'd':
                printf("dev mode\n");
                is_ap = false;
                break;
            case 'a':
                printf("ap mode\n");
                is_ap = true;
                break;
            case 'g':
                printf("get info\n");
                is_getinfo = true;
                break;
			case 'H':
                printf("reboot ...\n");
                is_reboot = true;
                break;
            case 'k':
                printf("close socket ...\n");
                is_close_all_socket = true;
                break;    
            case 's':
                slot = atoi(optarg);
                printf("slot %d\n", slot);
                break;
            case 'S':
                ioctl_slot = atoi(optarg);
                printf("ioctl_slot %d\n", ioctl_slot);
                break;
            case 'm':
                mcs = atoi(optarg);
                printf("mcs = %d\n",mcs);
                break;
            case 'b':
                bandwidth = atoi(optarg);
                printf("bandwidth = %d\n",bandwidth);
                break;
            case 'P':
                power = atoi(optarg);
                printf("power = %d\n",power);
                break;
            case 'c':
                chan = atoi(optarg);
                printf("chan = %d\n",chan);
                break;
            case 'C':
                compliance_mode = atoi(optarg);
                printf("compliance_mode = %d\n",compliance_mode);
                break;
            case 'r':
                role = atoi(optarg);
                printf("remote role = %d\n",role);
                break;
            case 'G':
                is_getcfg = true;
                printf("get cfg\n");
                break;
			case 'R':
                is_resetcfg = true;
                printf("reset cfg\n");
                break;
            case 't':
                timeout = atoi(optarg);
                printf("bb_ioctl timeout %d\n", timeout);
                break;
            case 'e':
                is_enable_bb_rf = true;
                bb_rf_enable = atoi(optarg);
                printf("bb_rf_enable %d\n", bb_rf_enable);
                break;
            case 'p':
                printf("plug test\n");
                is_plug_test = true;
                break;
            case 'E':
                printf("event register test\n");
                is_event_reg = true;
                break;
            case 'T':
                is_connect_test = true;
                printf("connect test\n");
                break;
            case 'o':
                port = atoi(optarg);
                printf("daemon port %d\n", port);
                break;
            case 'i':
                strcpy(ip_str, optarg);
                printf("daemon ip %s\n", ip_str);
                break;
			case 'v':
                is_get_version = true;
                printf("get version\n");
                break;
            case 'B':
                band = optarg;
                printf("Band set to %s\n", band);
                break;
            case 'x':
                printf("set tx rx\n");
                direction = atoi(optarg);
                if (direction != 0 && direction != 1) {
                    printf("Invalid direction: %d (only 0=RX or 1=TX is supported)\n", direction);
                    return -EINVAL;
                }
                printf("Direction set to %d (0=RX, 1=TX)\n", direction);
                break;
            case 'X':
                printf("set tx rx\n");
                is_tx_bandwith;
                break;
            case 'M':
                set_minidb = true;
                printf("Will save band setting to minidb (persistent)\n");
                break;
            case 'f':
                is_frame_change=true;
                frame_mode = atoi(optarg);
                break;
            default:
                printf("unknow cmd param !\n");
                bb_test_Usage(argv[0]);
                return -1;
        }
    }

    if (is_connect_test) {
        s32Ret = bb_host_connect_test(ip_str, port);
    }

    /* ==================Build connection with 8030(start)================ */
    /* Connect to the daemon */
    s32Ret = bb_host_connect(&phost, ip_str, port);
    if(s32Ret)
    {
        printf("bb connect error,ret=%d\n",s32Ret);
        //bb_deinit();
        return -1;
    }

    printf("bb connect success.\n");

    /* get dev list of the 8030 */
    dev_num = bb_dev_getlist(phost,&devs);
    if (dev_num <= 0) {
        printf("Get no device!\n");
        goto done;
    }

    printf("dev_num = %d\n", dev_num);

    /* Open the dev 8030 */
    bb_handle = bb_dev_open(devs[0]);
    if (!bb_handle) {
        printf("bb_dev_open error\n");
        bb_dev_freelist(devs);
        goto done;
    }

    printf("bb_handle success!\n");

    bb_dev_freelist(devs);

    if (is_getinfo) {
        bb_info_dump();
    }

    if (is_getcfg) {
        bb_cfg_dump();
    }
  if (is_reboot) {
        bb_reboot();
    }
    if (is_close_all_socket) {
        bb_close_socket();
    }

    if (is_getcfg) {
        bb_cfg_dump();
    }
    if (is_resetcfg) {
        bb_cfg_reset();
    }
    if (is_get_version) {
        bb_get_version();
    }
  

    if (band != NULL && direction != -1) {
        printf("\n==================== Band Setting ====================\n");
    
        if (direction == 0) {  // RX方向
            ret = set_rx_band();
        } else {                // TX方向（已补充自动模式）
            ret = set_tx_band();
        }
    
        // 检查频段设置是否成功
        if (ret != 0) {
            printf("Band setting failed, ret = %d\n", ret);
        } else {
            printf("Band setting completed!\n");
    
            // 如果需要写入minidb（永久生效），且普通设置成功
            if (set_minidb) {
                printf("\n--- Saving setting to minidb  ---\n");
                if(0==direction)
                {
                    ret = set_self_band_to_minidb();
                    if (ret != 0) {
                    printf("Saving to minidb failed, ret = %d\n", ret);
                    } else {
                        printf("Saved to minidb completed!\n");
                    }
                }
                if(1==direction)
                {
                    ret = set_peer_band_to_minidb();
                    if (ret != 0) {
                    printf("Saving to minidb failed, ret = %d\n", ret);
                    } else {
                        printf("Saved to minidb completed!\n");
                    }
                }
            }
        }
        printf("======================================================\n");
    } else if (band != NULL || direction != -1) {
        // 仅传入一个参数时报错（必须同时指定频段和方向）
        printf("Error: Both -B (band) and -t (direction) must be specified!\n");
        bb_dev_close(bb_handle);    // 关闭设备
        bb_host_disconnect(phost);  // 断开连接
        return -1;
    }

    if (is_frame_change)
    {
        if(frame_mode==1 || frame_mode==0)
        {
            set_frame_change_mode(frame_mode);
        }
        else{
            printf("-f need 1 or 0");
        }
    }
    


    if (is_enable_bb_rf) {
        bb_set_rf_t in;
        in.state = bb_rf_enable;
        in.dir = BB_DIR_RX;
        in.rf_path = BB_RF_PATH_A;
        ar8030_ioctl(bb_handle, BB_SET_RF, &in, sizeof(bb_set_rf_t), NULL, 0);
        in.rf_path = BB_RF_PATH_B;
        ar8030_ioctl(bb_handle, BB_SET_RF, &in, sizeof(bb_set_rf_t), NULL, 0);

        in.dir = BB_DIR_TX;
        in.rf_path = BB_RF_PATH_A;
        ar8030_ioctl(bb_handle, BB_SET_RF, &in, sizeof(bb_set_rf_t), NULL, 0);
        in.rf_path = BB_RF_PATH_B;
        ar8030_ioctl(bb_handle, BB_SET_RF, &in, sizeof(bb_set_rf_t), NULL, 0);
        usleep(2000*1000);
    }

    if (power == PWR_CFG_AUTO) {
        /* power auto */
        bb_set_pwr_auto_in.pwr_auto = 1;
        ar8030_ioctl(bb_handle, BB_SET_POWER_AUTO, &bb_set_pwr_auto_in, sizeof(bb_set_pwr_auto_in), NULL, 0);
    }
    else if (power >= 0) {
        /* power auto */
        bb_set_pwr_auto_in.pwr_auto = 0;
        ar8030_ioctl(bb_handle, BB_SET_POWER_AUTO, &bb_set_pwr_auto_in, sizeof(bb_set_pwr_auto_in), NULL, 0);

        /* power low */
        bb_set_pwr_in.usr = slot;//BB_USER_BR_CS;
        bb_set_pwr_in.pwr = power;
        ar8030_ioctl(bb_handle, BB_SET_POWER, &bb_set_pwr_in, sizeof(bb_set_pwr_in), NULL, 0);
    }
    /* set bandwidth*/
    if (bandwidth) {
        bb_set_bandwidth.bandwidth = bandwidth;
        if (is_tx_bandwith) {
            bb_set_bandwidth.dir = BB_DIR_TX;
        }
        else {
            bb_set_bandwidth.dir = BB_DIR_RX;
        }

        bb_set_bandwidth.slot = slot;
        ret = ar8030_ioctl(bb_handle, BB_SET_BANDWIDTH, &bb_set_bandwidth, sizeof(bb_set_bandwidth), NULL, 0);
        printf("BB_SET_BANDWIDTH bandwidth %d ret %d\n", bandwidth, ret);
        usleep(2000*1000);
    }

    /*set mcs*/
    if (mcs == MCS_CFG_AUTO) {
        bb_set_mcs_mode.auto_mode = true;
        bb_set_mcs_mode.slot = slot;
        s32Ret = ar8030_ioctl(bb_handle, BB_SET_MCS_MODE, (void*)&bb_set_mcs_mode, sizeof(bb_set_mcs_mode), NULL, 0);
        if (s32Ret) {
            printf("set mcs mode err! ret = %d\n",s32Ret );
            return -1;
        }
        usleep(2000*1000);
    }
    else if (mcs >= 0){
        bb_set_mcs_mode.auto_mode = false;
        bb_set_mcs_mode.slot = slot;
        s32Ret = ar8030_ioctl(bb_handle, BB_SET_MCS_MODE, (void*)&bb_set_mcs_mode, sizeof(bb_set_mcs_mode), NULL, 0);
        if (s32Ret) {
            printf("set mcs mode err! ret = %d\n",s32Ret );
            return -1;
        }

        bb_set_mcs.mcs = mcs;
        bb_set_mcs.slot = 0;
        s32Ret = ar8030_ioctl(bb_handle, BB_SET_MCS, (void*)&bb_set_mcs, sizeof(bb_set_mcs), NULL, 0);
        if (s32Ret) {
            printf("set mcs err! ret = %d\n",s32Ret );
            return -1;
        }
        usleep(2000*1000);
    }

    /*set chan*/
    if (chan == CHAN_CFG_AUTO) {
        chan_mode.auto_mode = 1;
        s32Ret = ar8030_ioctl(bb_handle, BB_SET_CHAN_MODE,  &chan_mode, sizeof(chan_mode), NULL, 0);
        if (s32Ret) {
            printf("set mcs mode err! ret = %d\n",s32Ret );
            return -1;
        }

        bb_set_remote_t set_remote = {0};
        set_remote.slot = BB_SLOT_0;
        set_remote.type_bmp = (1<<BB_REMOTE_TYPE_CHAN_MODE)|(1<<BB_REMOTE_TYPE_TARGET_CHAN);
        set_remote.setting.auto_chan = chan_mode.auto_mode;
        set_remote.setting.target_chan = 0;
        ret = ar8030_ioctl(bb_handle, BB_SET_REMOTE, &set_remote, sizeof(set_remote), NULL, 0);
        if(ret){
            printf("[Ioctl Fail]BB_SET_REMOTE ERR, %d !\n",ret);
            return -2;
        }
        usleep(2000*1000);
    }
    else if (chan > 0) {

        band_mode.auto_mode=0;

        s32Ret = ar8030_ioctl(bb_handle, BB_SET_BAND_MODE,  &band_mode, sizeof(band_mode), NULL, 0);
        if (s32Ret) {
            printf("set band mode err! ret = %d\n",s32Ret );
            return -1;
        }
        usleep(200*1000);
        set_band.target_band=1;

        s32Ret = ar8030_ioctl(bb_handle, BB_SET_BAND, &set_band, sizeof(set_band), NULL, 0);
        if(s32Ret){
            printf("[Ioctl Fail]BB_SET_CHAN RX ERR, %d !\n",s32Ret);
            return -2;
        }

        usleep(200*1000);
        chan_mode.auto_mode = 0;
        s32Ret = ar8030_ioctl(bb_handle, BB_SET_CHAN_MODE,  &chan_mode, sizeof(chan_mode), NULL, 0);
        if (s32Ret) {
            printf("set mcs mode err! ret = %d\n",s32Ret );
            return -1;
        }

        set_chan.chan_dir = BB_DIR_RX;
        set_chan.chan_index = chan;
        s32Ret = ar8030_ioctl(bb_handle, BB_SET_CHAN, &set_chan, sizeof(set_chan), NULL, 0);
        if(s32Ret){
            printf("[Ioctl Fail]BB_SET_CHAN RX ERR, %d !\n",s32Ret);
            return -2;
        }

        bb_set_remote_t set_remote = {0};
        set_remote.slot = BB_SLOT_0;
        set_remote.type_bmp = (1 << BB_REMOTE_TYPE_TARGET_BAND) | (1 << BB_REMOTE_TYPE_CHAN_MODE) | (1 << BB_REMOTE_TYPE_TARGET_CHAN);
        set_remote.setting.auto_chan = 0;
        printf("set remote--------- !");
        set_remote.setting.target_chan = chan;
        set_remote.setting.target_band=1;
        ret = ar8030_ioctl(bb_handle, BB_SET_REMOTE, &set_remote, sizeof(set_remote), NULL, 0);
        if(ret){
            printf("[Ioctl Fail]BB_SET_REMOTE ERR, %d !",ret);
            return -2;
        }
        usleep(2000*1000);
    }

    /* set compliance_mode */
    if (compliance_mode >= 0) {
        bb_set_remote_t bb_set_remote;
        bb_set_remote.slot = slot;
        bb_set_remote.type_bmp = (1 << BB_REMOTE_TYPE_COMPLIANCE_MODE);
        bb_set_remote.setting.compliance_mode = compliance_mode;
        ar8030_ioctl(bb_handle, BB_SET_REMOTE, &bb_set_remote, sizeof(bb_set_remote), NULL, 0);

        bb_set_compliance_mode_t bb_set_compliance_mode;
        bb_set_compliance_mode.enable = compliance_mode;
        ar8030_ioctl(bb_handle, BB_SET_COMPLIANCE_MODE, &bb_set_compliance_mode, sizeof(bb_set_compliance_mode), NULL, 0);
        usleep(2000*1000);
    }

    if (role > 0)
    {
        prj_rpc_hdr_t *hdr, *hdr_out;
        prj_cmd_set_role_t *set_role;
        bb_set_prj_dispatch_in_t set_prj = {0};

        hdr=(prj_rpc_hdr_t *)set_prj.data;
        hdr->cmdid = PRJ_CMD_SET_ROLE;

        set_role = (prj_cmd_set_role_t*)hdr->data;
        set_role->role = role;

        s32Ret = ar8030_ioctl(bb_handle, BB_SET_PRJ_DISPATCH, &set_prj, sizeof(set_prj), NULL, 0);
        if (s32Ret) {
            printf("set role err! ret = %d",s32Ret);
        }
        else {
            printf("set role %d success!\n", role);
        }

        /* get role */
        bb_get_prj_dispatch_in_t get_prj_in = {0};
        bb_get_prj_dispatch_out_t get_prj_out = {0};
        prj_cmd_get_role_t *get_role = NULL;

        hdr=(prj_rpc_hdr_t *)get_prj_in.data;
        hdr->cmdid = PRJ_CMD_GET_ROLE;

        s32Ret = ar8030_ioctl(bb_handle, BB_GET_PRJ_DISPATCH, &get_prj_in, sizeof(get_prj_in), &get_prj_out, sizeof(get_prj_out));
        if (s32Ret) {
            printf("get role err! ret = %d",s32Ret);
        }
        else {
            hdr_out=(prj_rpc_hdr_t *)get_prj_out.data;

            get_role = (prj_cmd_get_role_t*)hdr_out->data;

            printf("get role success! role is %s\n", (get_role->role == 0)?"AP":"DEV");
        }
    }

    if (is_event_reg) {
        s32Ret = MID_UTIL_CreateDetachThread(bb_event_process, NULL, NULL);
        if(s32Ret < 0)
        {
            printf("create bb_event_process task fail!\n");
        }
    }

done:
    if (is_plug_test) {
        bb_dev_reg_hotplug_cb(phost, bb_event_hotplug, NULL);
        while(1) {
            usleep(1000*1000);
        }
    }

    return 0;
}